#!/usr/bin/env python
# -*- coding: utf-8 -*-

########################################################################
#                          Course Work                                 #
# Title: _____________________                                         #
# Author(s): Gudulin(a) A.O.                                           #
# Url: https://code.google.com/p/course-work/                          #
# Email: <gudulinanastya@gmail.com>                                    #
# License: GNU GPL v3                                                  #
########################################################################

import sys
import os
import mainWindow
import inputData
import resultWindow
#import compareWidget
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import numpy as np

class InputData(QDialog, inputData.Ui_Dialog):
    """Dialog with ability add tariffs and criteria"""
    def __init__(self, parent=None):
        super(InputData, self).__init__(parent)
        self.setupUi(self)
        self.setWindowTitle(u'Введите названия тарифов и критерии')
        self.addButton_t.clicked.connect(self.addTariff)
        self.delButton_t.clicked.connect(self.delTariff)
        self.addButton_c.clicked.connect(self.addCriterion)
        self.delButton_c.clicked.connect(self.delCriterion)
        self.accepted.connect(self.closeDialog)
        self.settings = QSettings('gudulina', 'course-work')
        criteriaList = self.settings.value('criteria').toString()
        if criteriaList:
            for name in criteriaList.split(';;'):
                if name:
                    self.listWidget_c.addItem(name)
        
        tariffsList = self.settings.value('tariffs').toString()
        if tariffsList:
            for name in tariffsList.split(';;'):
                if name:
                    self.listWidget_t.addItem(name)
    
    def addTariff(self):
        """Add tariff name to list"""
        name, ok = QInputDialog.getText(self, u'Введите название тарифа', 
                u'Название тарифа:')
        if ok:
            self.listWidget_t.addItem(name)

    def addCriterion(self):
        """Add criteria name to list"""
        name, ok = QInputDialog.getText(self, u'Введите название критерия', 
                u'Название критерия:')
        if ok:
            self.listWidget_c.addItem(name)
            
    def delCriterion(self):
        """Delete criteria name from list"""
        item = self.listWidget_c.takeItem(self.listWidget_c.currentRow())
        item = None
            
    def delTariff(self):
        """Delete tariff name from list"""
        item = self.listWidget_t.takeItem(self.listWidget_t.currentRow())
        item = None

    def closeDialog(self):
        """Save tariffs and criteria to the config file"""
        tariffsList = ''
        for i in range(self.listWidget_t.count()):
            tariffsList += self.listWidget_t.item(i).text() + ';;'
        self.settings.setValue('tariffs', tariffsList)
        criteriaList = ''
        for i in range(self.listWidget_c.count()):
            criteriaList += self.listWidget_c.item(i).text() + ';;'
        self.settings.setValue('criteria', criteriaList)


class ResultWindow(QDialog, resultWindow.Ui_Form):
    """Result window class"""
    def __init__(self, args, parent=None):
        super(ResultWindow, self).__init__(parent)
        self.setupUi(self)
        self.setWindowTitle(u'Результаты')
        self.okButton.clicked.connect(self.close)
        self.settings = QSettings('gudulina', 'course-work')
        self.matrix = []; m = []; self.vector = []
        self.rows = args[0]
        self.columns = self.rows
        # Get criteria matrix
        for i in range(self.rows):
            for j in range(self.rows):
                m.append(float(self.settings.value('MatrixCriteria/'
                        + str(i)+'-'+str(j)).toString()))
            self.matrix.append(m)
            g = float(self.settings.value('NormalizedVector/' + str(i)).toString())
            self.vector.append(g) # Get criteria normalized vector
            m = []

        # Get tariffs matrix
        self.tariffsMatrix = []; self.tariffsVector = []
        self.maxCriteriaNumber = self.vector.index(max(self.vector))
        self.tariffsCount = args[1]
        for i in range(self.tariffsCount):
            for j in range(self.tariffsCount):
                arg = self.settings.value('MatrixTariffs-'+
                        str(self.maxCriteriaNumber)+'/'+ str(i)+'-'+str(j)).toString()
                m.append(float(arg))
            self.tariffsMatrix.append(m)
            g = float(self.settings.value('TariffsNormalizedVector-'+
                    str(self.maxCriteriaNumber)+'/' + str(i)).toString())
            self.tariffsVector.append(g) # Get tariffs normalized vector
            m = []

        # Set settings for criteria tables
        self.criteria = QStringList(args[2])
        self.tableWidget.setRowCount(self.rows)
        self.tableWidget.setColumnCount(self.columns+1)
        self.vectorTable.setRowCount(self.rows)
        self.vectorTable.setColumnCount(1)
        
        # Fill the table of criteria
        itemsPoints = [9.0, 7.0, 5.0, 3.0, 1.0, 0.33, 0.2, 0.14, 0.11]
        itemsEquivs = ['9', '7', '5', '3', '1', '1/3', '1/5', '1/7', '1/9']
        for i in range(self.rows):
            self.tableWidget.setItem(i, 0,
                    QTableWidgetItem(QString(self.criteria[i])))
            for j in range(self.columns):
                N = round((self.matrix[i][j]), 2)
                m = itemsEquivs[itemsPoints.index(N)]
                self.tableWidget.setItem(i, j+1,
                        QTableWidgetItem(QString(m)))
            self.vectorTable.setItem(i, 0, QTableWidgetItem(
                    QString(str(self.vector[i]))))

        # Set settings for tariffs tables
        self.criterionLine.setText(args[2][self.maxCriteriaNumber])
        self.tariffs = QStringList(args[3])
        self.tableWidget_t.setRowCount(self.tariffsCount)
        self.tableWidget_t.setColumnCount(self.tariffsCount+1)
        self.vectorTable_t.setRowCount(self.tariffsCount)
        self.vectorTable_t.setColumnCount(1)

        # Fill the table of tariffs
        for i in range(self.tariffsCount):
            self.tableWidget_t.setItem(i, 0, QTableWidgetItem(QString(self.tariffs[i])))
            for j in range(self.tariffsCount):
                N = round((self.tariffsMatrix[i][j]), 2)
                m = itemsEquivs[itemsPoints.index(N)]
                self.tableWidget_t.setItem(i, j+1, QTableWidgetItem(QString(m)))
            self.vectorTable_t.setItem(i, 0, QTableWidgetItem(
                    QString(str(self.tariffsVector[i]))))

        # Set the best of tariffs name
        maxIndex = self.tariffsVector.index(max(self.tariffsVector))
        bestTarif = args[3][maxIndex]
        self.bestTarifLine.setText(bestTarif)


#~ class CompareWidget(QDialog, compareWidget.Ui_Form):
    #~ """Compare widget with two tariffs comparison"""
    #~ def __init__(self, tarif1, tarif2, criterion, itemsList, parent=None):
        #~ super(CompareWidget, self).__init__(parent)
        #~ self.setupUi(self)
        #~ self.tarif1.setText(tarif1)
        #~ self.tarif2.setText(tarif2)
        #~ self.criterion.setText(criterion)
        #~ self.nextButton.clicked.connect(self.returnItem)
        #~ self.comboBox.activated.connect(self.closeWidget)
        #~ self.comboBox.addItems(QStringList(itemsList))
        #~ self.item = ''
#~ 
    #~ def returnItem(self):
        #~ self.item = self.comboBox.currentText()
        #~ return self.item
    #~ 
    #~ def closeWidget(self):
        #~ self.close()


class MainWindow(QMainWindow, mainWindow.Ui_MainWindow):
    """Main window class"""
    endCompareSignal = pyqtSignal(str)
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.setWindowTitle(u'Choiceoftariff v0.1')
        pic = QPixmap(); pic.load("images/logo_t.re.jpg")
        self.logo.setPixmap(pic)
        self.logo.setFixedSize(QSize(180, 100))
        self.inputData = InputData(self)
        self.inputButton.clicked.connect(self.newDialogData)
        self.inputData.accepted.connect(self.checkInputData)
        self.startButton.clicked.connect(self.startCompare)
        self.endCompareSignal.connect(self.showResult)
        self.settings = QSettings('gudulina', 'course-work')
        
    def newDialogData(self):
        """Slot called dialog with add tariffs"""
        self.inputData.show()

    def checkInputData(self):
        """Check input data like number of criteria and tariffs"""
        #TODO: add input data handler
        #then we can do it:
        self.startButton.setEnabled(1)

    def getTariffsNames(self):
        """Get number of tariffs from config file"""
        names = []
        tariffsList = self.settings.value('tariffs').toString()
        if tariffsList:
            for name in tariffsList.split(';;'):
                if name:
                    names.append(unicode(name))
        return names

    def getCriteriaNames(self):
        """Get number of criteria from config file"""
        names = []
        criteriaList = self.settings.value('criteria').toString()
        if criteriaList:
            for name in criteriaList.split(';;'):
                if name:
                    names.append(unicode(name))
        return names

    def endCompare(self):
        """Create SIGNAL about end compare"""
        self.endCompareSignal.emit('')

    def showResult(self):
        criteria = self.getCriteriaNames()
        tariffs = self.getTariffsNames()
        tariffsCount = len(tariffs)
        criteriaCount = len(criteria)
        self.rw = ResultWindow([criteriaCount, tariffsCount, criteria, tariffs], self)
        self.rw.show()

    def startCompare(self):
        """Create widget for each pare of tariffs"""
        tariffs = self.getTariffsNames()
        n = len(tariffs)
        criteria = self.getCriteriaNames()

        itemsList = [u'A абсолютно превосходит B', u'A явно важнее В',
                u'А значительно важнее B', u'А незначительно важнее В',
                u'A и В одинаково важны', u'B незначительно важнее A',
                u'B значительно важнее A', u'B явно важнее A',
                u'B абсолютно превосходит A']
        itemsPoints = [9, 7, 5, 3, 1, 1./3, 1./5, 1./7, 1./9]

        matrixIndex = 0
        # Compare every tariff
        for criterion in criteria:
            matrixIndex += 1
            matrix = self.getCleanMatrix(n)
            for i in range(0, n-1):
                for j in range(i+1, n):
                    text = QString(u'Сравниваем A: \"' +
                            tariffs[i] + u'\" и B: \"' +
                            tariffs[j] + u'\"\n\nпо критерию \"' +
                            criterion + '\"')
                    item, ok = QInputDialog.getItem(self, u'Сравнение',
                            text, itemsList, 0, True)
                    #~ self.cw = CompareWidget(tariffs[i], tariffs[j], criterion, itemsList)
                    #~ item = u'A абсолютно превосходит B'
                    #~ item = self.cw.returnItem()
                    #~ self.cw.exec_()
                    itemIndex = itemsList.index(unicode(item))
                    
                    if ok:
                        #print i, j, unicode(item), itemsPoints[itemIndex]
                        matrix[i][j] = itemsPoints[itemIndex]
                        matrix[j][i] = 1./itemsPoints[itemIndex]
                    else:
                        #TODO: Send an error message about aborting operation
                        pass

            # Get normalized vector for current matrix
            g = self.getNormalizedVector(matrix)
            # Save matrix to config file
            for i in range(n):
                for j in range(n):
                    self.settings.setValue('MatrixTariffs-' + str(matrixIndex-1)
                            + '/' + str(i) + '-' + str(j), matrix[i][j])
                self.settings.setValue('TariffsNormalizedVector-' + str(matrixIndex-1) +
                        '/'+str(i), str(np.around(g[i].real, decimals=4)))

        # Compare every criterion
        n = len(criteria)
        matrixCriteria = self.getCleanMatrix(n)
        for i in range(0, n-1):
            for j in range(i+1, n):
                text = QString(u'Сравниваем A: \"' +
                        criteria[i] + u'\" и B: \"' +
                        criteria[j] + '\"')
                item, ok = QInputDialog.getItem(self, u'Сравнение',
                        text, itemsList, 0, True)
                itemIndex = itemsList.index(unicode(item))

                if ok:
                    #print i, j, unicode(item), itemsPoints[itemIndex]
                    matrixCriteria[i][j] = itemsPoints[itemIndex]
                    matrixCriteria[j][i] = 1./itemsPoints[itemIndex]
                else:
                    #TODO: Send an error message about aborting operation
                    pass
                    
        g = self.getNormalizedVector(matrixCriteria)
        for i in range(n):
            for j in range(n):
                self.settings.setValue('MatrixCriteria/' + str(i) +'-'+
                        str(j), matrixCriteria[i][j])
            self.settings.setValue('NormalizedVector/' + str(i),
                    str(np.around(g[i].real, decimals=4)))

        self.endCompare()
            
    def getCleanMatrix(self, n):
        """Return clean matrix full of 0 and 1 on main diagonal"""
        matrix = []
        for i in range(0, n):
            m = []
            for j in range(0, n):
                if i == j:
                    m.append(1)
                else:
                    m.append(0)
            matrix.append(m)
        return matrix

    def vectorSort(self, l1, l2):
        """l1 -собственные числа, а l2 - с.в"""
        #TODO: add human brief
        for i in xrange(len(l1)-1):
            for j in xrange(len(l1)-1):
                if l1[j] < l1[j+1]:
                    b = l1[j+1]
                    l1[j+1] = l1[j]
                    l1[j] =  b
                    a = l2[j+1].copy()
                    l2[j+1] = l2[j]
                    l2[j] = a
        return l1, l2

    def getNormalizedVector(self, matrix):
        """Get magic vector"""
        #TODO: add human brief
        a = np.mat(matrix)
        #print 'a:\n', a
        la, v = np.linalg.eig(a) # ищем в матрице собственные числа и \
                                 #собственные вектора
        la, v = self.vectorSort(la, v)
        #print 'eigenvalues of a:\n', la # собственные числа по убыванию
        #print 'eigenvectors of a:\n', v # собственные вектора в \
                                        #соответствии с сортировкой с.ч.
        c = v[0]
        #print c
        d = c.A # преобразуем матрицу в массив
        n = len(d[0])
        s = 0
        for i in xrange(n):
            s += d[0,i] ** 2
        s = s ** 0.5
        #print s
        g = []
        for i in xrange(n):
            #print d[0, i] / s
            g.append(d[0, i] / s)
        return g # нормированный вектор


app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
app.exec_()
